#include "ShaderLoader.h"
#include "Log.h"
#include <glad/glad.h>
#include <fstream>

namespace SCION_RENDERING
{
  GLuint ShaderLoader::CreateProgram(const std::string &vertexShader, const std::string &fragmentShader)
  {
    const GLuint program = glCreateProgram();
    const GLuint vertex = CompileShader(GL_VERTEX_SHADER, vertexShader);       // 修正：vertexShader
    const GLuint fragment = CompileShader(GL_FRAGMENT_SHADER, fragmentShader); // 修正：fragmentShader
    if (vertex == 0 || fragment == 0)
    {
      return 0;
    }
    if (!LinkShaders(program, vertex, fragment))
    {
      SCION_ERROR("Failed to Link Shaders!");
      return 0;
    }
    return program;
  }

  GLuint ShaderLoader::CompileShader(GLuint shaderType, const std::string &filepath) // 修正：GLuint
  {
    const GLuint shaderID = glCreateShader(shaderType);
    std::ifstream ifs(filepath);
    if (ifs.fail())
    {
      SCION_ERROR("Shader Failed to open [" + filepath + "]");
      return 0;
    }
    std::string contents{""};
    std::string line;
    while (std::getline(ifs, line))
    {
      contents += line + "\n";
    }
    ifs.close();

    const char *contentsPtr = contents.c_str();
    glShaderSource(shaderID, 1, &contentsPtr, nullptr);
    glCompileShader(shaderID); // 添加：缺少编译调用
    if (!CompileSuccess(shaderID))
    {
      SCION_ERROR("Failed to compile shader [" + filepath + "]");
      return 0;
    }
    return shaderID;
  }

  bool ShaderLoader::CompileSuccess(GLuint shader) // 修正：GLuint
  {
    GLint status; // 修正：GLint
    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);

    if (status != GL_TRUE)
    {
      GLint maxLength; // 修正：GLint
      glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);

      std::string errorLog(maxLength, ' ');                            // 修正：errorLog，使用空格初始化
      glGetShaderInfoLog(shader, maxLength, nullptr, errorLog.data()); // 修正：添加获取日志

      SCION_ERROR("Shader compilation failed: " + errorLog); // 修正：直接使用errorLog

      glDeleteShader(shader);
      return false;
    }
    return true;
  }

  bool ShaderLoader::IsProgramValid(GLuint program) // 修正：GLuint
  {
    GLint status; // 修正：GLint
    glGetProgramiv(program, GL_LINK_STATUS, &status);
    if (status != GL_TRUE)
    {
      GLint maxLength; // 修正：GLint 和 maxLength
      glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
      std::string errorLog(maxLength, ' ');                              // 修正：errorLog 和 maxLength
      glGetProgramInfoLog(program, maxLength, nullptr, errorLog.data()); // 修正：添加获取日志
      SCION_ERROR("Shader's failed to link: " + errorLog);                  // 修正：errorLog
      return false;
    }

    return true;
  }

  bool ShaderLoader::LinkShaders(GLuint program, GLuint vertexShader, GLuint fragmentShader)
  {
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);

    glLinkProgram(program);

    if (!IsProgramValid(program)) // 修正：添加 ! 否定
    {
      glDetachShader(program, vertexShader); // 修正：先分离再删除
      glDetachShader(program, fragmentShader);
      glDeleteShader(vertexShader);
      glDeleteShader(fragmentShader);
      glDeleteProgram(program);
      return false;
    }

    glDetachShader(program, vertexShader); // 修正：链接成功后分离着色器
    glDetachShader(program, fragmentShader);
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    return true;
  }

  std::shared_ptr<Shader> ShaderLoader::Create(const std::string &vertexShaderPath, const std::string &fragmentShaderPath) // 修正：fragmentShaderPath
  {
    GLuint program = CreateProgram(vertexShaderPath, fragmentShaderPath);

    if (program)
    {
      return std::make_shared<Shader>(program, vertexShaderPath, fragmentShaderPath);
    }
    return nullptr;
  }
}